using UnityEngine;
using System.Collections;
using UnityEditor;

[AddComponentMenu ( "Chromatic2D/C2DSprite" )]
public class C2DSprite : MonoBehaviour 
{	
	//Enum for sprites property
	
	public enum AnchorPoint
	{
		Top_Left = 0,
		Top_Right,
		Middle,
		Bottom_Left,
		Bottom_Right
	}
	
	//Base sprite config value
	
	[HideInInspector][SerializeField]
	protected MeshRenderer 				m_MeshRenderer	= null;
	[HideInInspector][SerializeField]
	protected MeshFilter 				m_MeshFilter	= null;
	[HideInInspector][SerializeField]
	private int 						m_nSpriteIndex 	= 0;
	[HideInInspector][SerializeField]
	private AnchorPoint 				m_AnchorPoint 	= AnchorPoint.Middle;
	[HideInInspector][SerializeField]
	protected UFTAtlasMetadata 			m_Atlas 		= null;	
	
	private Mesh 						m_Mesh			= null;
	
	#if UNITY_EDITOR
	
	/// <summary>
	/// Creates a default sprite.
	/// </summary>
	[MenuItem("GameObject/Create Other/C2DSsprite")]
	public static void CreateC2DSprite()
	{
		GameObject go = new GameObject("New Sprite");
		go.AddComponent( typeof(C2DSprite) );
	}
	
	#endif
	
	void Awake()
	{
		InitSprite();
	}
	
	void OnDrawGizmosSelected()
	{
		//Ensure each Instance is creating is own mesh
		InitMesh();
	}
	
	/// <summary>
	/// Gets the sprite index in the atlas
	/// </summary>
	public int GetSpiteIndex()
	{
		return m_nSpriteIndex;
	}
	
	/// <summary>
	/// Set the sprite index in the atlas
	/// </summary
	public void SetSpriteIndex( int index )
	{
		if( index < m_Atlas.entries.Length &&  index >= 0  )
		{
			m_nSpriteIndex = index;
		}
		else
		{
			m_nSpriteIndex = 0;
		}
		
		UpdateSprite();
	}
		
	/// <summary>
	/// Gets the atlas Metadata
	/// </summary>
	public UFTAtlasMetadata GetAtlas()
	{
		return m_Atlas;
	}
	
	/// <summary>
	/// Sets the atlas Metadata
	/// </summary>
	public virtual void SetAtlas( UFTAtlasMetadata atlas )
	{
		//if null ignore the command
		if( atlas != null )
		{
			m_Atlas = atlas;
			m_MeshRenderer.sharedMaterial = m_Atlas.material;
			SetSpriteIndex( m_nSpriteIndex );
			UpdateSprite();
		}
	}
	
	/// <summary>
	/// Sets the anchor point for this sprite
	/// </summary>
	public void SetAnchor( AnchorPoint anchor )
	{
		m_AnchorPoint = anchor;
		UpdateSprite();
	}
	
	/// <summary>
	/// Gets the anchor for this spriye
	/// </summary>
	public AnchorPoint GetAnchor()
	{
		return m_AnchorPoint;
	}
	
	/// <summary>
	/// Determines whether this instance is initialized.
	/// </summary>
	public bool IsInitialized()
	{
		return (m_MeshFilter != null && m_MeshRenderer != null );
	}
	
	
	/// <summary>
	/// If instance doesn't have his own mesh create it
	/// </summary>
	public void InitMesh()
	{
		if( m_Mesh == null )
		{
			if( IsInitialized() )
			{
				
				m_Mesh = new Mesh();	
				m_MeshFilter.mesh = m_Mesh;
				UpdateSprite();
			}
		}
	}
	
	
	/// <summary>
	/// Inits the sprite.
	/// </summary>
	public void InitSprite()
	{
		if( !IsInitialized() )
		{	
			m_MeshRenderer = (MeshRenderer)GetComponent(typeof(MeshRenderer) );
			m_MeshFilter = (MeshFilter)GetComponent(typeof(MeshFilter) );
			
			if(  m_MeshRenderer == null )
			{
				m_MeshRenderer = (MeshRenderer)gameObject.AddComponent( typeof(MeshRenderer) );
			}
	
			if(  m_MeshFilter == null )
			{
				m_MeshFilter = (MeshFilter)gameObject.AddComponent( typeof(MeshFilter) );
			}
			
			if( m_Atlas == null )
			{
				//Load Dummy
				m_Atlas = (UFTAtlasMetadata)Resources.Load("Dummy/DummySprite",typeof(UFTAtlasMetadata) );
			}			

			if( m_MeshRenderer.sharedMaterial == null && m_Atlas.material != null )
			{
				m_MeshRenderer.sharedMaterial = m_Atlas.material;
			}
		}
		
		InitMesh();
	}
	
	/// <summary>
	/// Updates the quad.
	/// </summary>
	private void UpdateQuad( float xmin, float xmax, float ymin, float ymax, float uMin,float uMax, float vMin,float vMax )
	{
		Vector3[] vertices = new Vector3[4];
		
		vertices[0] = new Vector3( xmax, ymax, 0);
		vertices[1] = new Vector3( xmax, ymin, 0);
		vertices[2] = new Vector3( xmin, ymax, 0);
		vertices[3] = new Vector3( xmin, ymin, 0);
		
		Vector2[] uv = new Vector2[4];
		
		uv[0] = new Vector2(uMax, vMax);
		uv[1] = new Vector2(uMax, vMin);
		uv[2] = new Vector2(uMin, vMax);
		uv[3] = new Vector2(uMin, vMin);
		
		int[] triangles = new int[]
		{
			0, 1, 2,
			2, 1, 3,
		};

		m_Mesh.vertices = vertices;
		m_Mesh.uv = uv;
		m_Mesh.triangles = triangles;
	}
	
	/// <summary>
	/// Updates the sprite.
	/// </summary>
	public void UpdateSprite()
	{	
		UFTAtlasEntryMetadata data = m_Atlas.entries[ m_nSpriteIndex ];
		
		switch( m_AnchorPoint )
		{
			case AnchorPoint.Middle :
			
				float HalfWidth = data.pixelRect.width/2.0f;
				float HalfHeight = data.pixelRect.height/2.0f;
			
				UpdateQuad
				(
					-HalfWidth,
					HalfWidth,
					-HalfHeight,
					HalfHeight,
					data.uvRect.x,
					data.uvRect.x + data.uvRect.width,
					data.uvRect.y,
					data.uvRect.y + data.uvRect.height
				);
			
			break;
			
			case AnchorPoint.Top_Left :
			
				UpdateQuad
				(
					0f,
					data.pixelRect.width,
					-data.pixelRect.height,
					0f,
					data.uvRect.x,
					data.uvRect.x + data.uvRect.width,
					data.uvRect.y,
					data.uvRect.y + data.uvRect.height
				);
			
			break;
			
			case AnchorPoint.Top_Right :
			
				UpdateQuad
				(
					-data.pixelRect.width,
					0,
					-data.pixelRect.height,
					0f,
					data.uvRect.x,
					data.uvRect.x + data.uvRect.width,
					data.uvRect.y,
					data.uvRect.y + data.uvRect.height
				);
			
			break;
			
			case AnchorPoint.Bottom_Left :
			
				UpdateQuad
				(
					0f,
					data.pixelRect.width,
					0f,
					data.pixelRect.height,
					data.uvRect.x,
					data.uvRect.x + data.uvRect.width,
					data.uvRect.y,
					data.uvRect.y + data.uvRect.height
				);
			
			break;
			
				case AnchorPoint.Bottom_Right :
			
				UpdateQuad
				(
					-data.pixelRect.width,
					0f,
					0f,
					data.pixelRect.height,
					data.uvRect.x,
					data.uvRect.x + data.uvRect.width,
					data.uvRect.y,
					data.uvRect.y + data.uvRect.height
				);
			
			break;
		}
	}
}
